package com.tonann.system.service.impl;

import com.tonann.common.annotation.DataScope;
import com.tonann.common.constant.UserConstants;
import com.tonann.common.core.domain.TreeSelect;
import com.tonann.common.core.domain.entity.SysPlace;
import com.tonann.common.core.domain.entity.SysRole;
import com.tonann.common.core.domain.entity.SysUser;
import com.tonann.common.core.text.Convert;
import com.tonann.common.exception.ServiceException;
import com.tonann.common.utils.SecurityUtils;
import com.tonann.common.utils.StringUtils;
import com.tonann.common.utils.spring.SpringUtils;
import com.tonann.system.mapper.SysPlaceMapper;
import com.tonann.system.mapper.SysRoleMapper;
import com.tonann.system.service.ISysPlaceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 空间位置管理 服务实现
 *
 * @author tonann
 */
@Service
public class SysPlaceServiceImpl implements ISysPlaceService
{
    @Autowired
    private SysPlaceMapper placeMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    /**
     * 查询空间位置管理数据
     *
     * @param place 空间位置信息
     * @return 空间位置信息集合
     */
    @Override
    @DataScope(placeAlias = "p")
    public List<SysPlace> selectPlaceList(SysPlace place)
    {
        return placeMapper.selectPlaceList(place);
    }

    @Override
    public List<SysPlace> selectPlaceAll(SysPlace place) {
        return placeMapper.selectPlaceAll(place);
    }

    /**
     * 查询空间位置树结构信息
     *
     * @param place 空间位置信息
     * @return 空间位置树信息集合
     */
    @Override
    public List<TreeSelect> selectPlaceTreeList(SysPlace place)
    {
        List<SysPlace> places = SpringUtils.getAopProxy(this).selectPlaceList(place);
        return buildPlaceTreeSelect(places);
    }

    /**
     * 构建前端所需要树结构
     *
     * @param places 空间位置列表
     * @return 树结构列表
     */
    @Override
    public List<SysPlace> buildPlaceTree(List<SysPlace> places)
    {
        List<SysPlace> returnList = new ArrayList<SysPlace>();
        List<Long> tempList = new ArrayList<Long>();
        for (SysPlace place : places)
        {
            tempList.add(place.getPlaceId());
        }
        for (SysPlace place : places)
        {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(place.getParentId()))
            {
                recursionFn(places, place);
                returnList.add(place);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = places;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param places 空间位置列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildPlaceTreeSelect(List<SysPlace> places)
    {
        List<SysPlace> placeTrees = buildPlaceTree(places);
        return placeTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 根据角色ID查询空间位置树信息
     *
     * @param roleId 角色ID
     * @return 选中空间位置列表
     */
    @Override
    public List<Long> selectPlaceListByRoleId(Long roleId)
    {
        SysRole role = roleMapper.selectRoleById(roleId);
        return placeMapper.selectPlaceListByRoleId(roleId, role.isPlaceCheckStrictly());
    }

    /**
     * 根据空间位置ID查询信息
     *
     * @param placeId 空间位置ID
     * @return 空间位置信息
     */
    @Override
    public SysPlace selectPlaceById(Long placeId)
    {
        return placeMapper.selectPlaceById(placeId);
    }

    /**
     * 根据ID查询所有子空间位置（正常状态）
     *
     * @param placeId 空间位置ID
     * @return 子空间位置数
     */
    @Override
    public int selectNormalChildrenPlaceById(Long placeId)
    {
        return placeMapper.selectNormalChildrenPlaceById(placeId);
    }

    /**
     * 是否存在子节点
     *
     * @param placeId 空间位置ID
     * @return 结果
     */
    @Override
    public boolean hasChildByPlaceId(Long placeId)
    {
        int result = placeMapper.hasChildByPlaceId(placeId);
        return result > 0;
    }

    /**
     * 查询空间位置是否存在用户
     *
     * @param placeId 空间位置ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkPlaceExistUser(Long placeId)
    {
        int result = placeMapper.checkPlaceExistUser(placeId);
        return result > 0;
    }

    /**
     * 校验空间位置名称是否唯一
     *
     * @param place 空间位置信息
     * @return 结果
     */
    @Override
    public String checkPlaceNameUnique(SysPlace place)
    {
        Long placeId = StringUtils.isNull(place.getPlaceId()) ? -1L : place.getPlaceId();
        SysPlace info = placeMapper.checkPlaceNameUnique(place.getPlaceName(), place.getParentId());
        if (StringUtils.isNotNull(info) && info.getPlaceId().longValue() != placeId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验空间位置是否有数据权限
     *
     * @param placeId 空间位置id
     */
    @Override
    public void checkPlaceDataScope(Long placeId)
    {
        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
        {
            SysPlace place = new SysPlace();
            place.setPlaceId(placeId);
            List<SysPlace> places = SpringUtils.getAopProxy(this).selectPlaceList(place);
            if (StringUtils.isEmpty(places))
            {
                throw new ServiceException("没有权限访问空间位置数据！");
            }
        }
    }

    /**
     * 新增保存空间位置信息
     *
     * @param place 空间位置信息
     * @return 结果
     */
    @Override
    public int insertPlace(SysPlace place)
    {
        SysPlace info = placeMapper.selectPlaceById(place.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (info != null  && !UserConstants.DEPT_NORMAL.equals(info.getStatus()))
        {
            throw new ServiceException("空间位置停用，不允许新增");
        }
        String ancestors = info == null ? "": (info.getAncestors()  + ",");
        place.setAncestors(ancestors + place.getParentId());
        return placeMapper.insertPlace(place);
    }

    /**
     * 修改保存空间位置信息
     *
     * @param place 空间位置信息
     * @return 结果
     */
    @Override
    public int updatePlace(SysPlace place)
    {
        SysPlace newParentPlace = placeMapper.selectPlaceById(place.getParentId());
        SysPlace oldPlace = placeMapper.selectPlaceById(place.getPlaceId());
        if (StringUtils.isNotNull(newParentPlace) && StringUtils.isNotNull(oldPlace))
        {
            String newAncestors = newParentPlace.getAncestors() + "," + newParentPlace.getPlaceId();
            String oldAncestors = oldPlace.getAncestors();
            place.setAncestors(newAncestors);
            updatePlaceChildren(place.getPlaceId(), newAncestors, oldAncestors);
        }
        int result = placeMapper.updatePlace(place);
        if (UserConstants.DEPT_NORMAL.equals(place.getStatus()) && StringUtils.isNotEmpty(place.getAncestors())
                && !StringUtils.equals("0", place.getAncestors()))
        {
            // 如果该空间位置是启用状态，则启用该空间位置的所有上级空间位置
            updateParentPlaceStatusNormal(place);
        }
        return result;
    }

    /**
     * 修改该空间位置的父级空间位置状态
     *
     * @param place 当前空间位置
     */
    private void updateParentPlaceStatusNormal(SysPlace place)
    {
        String ancestors = place.getAncestors();
        Long[] placeIds = Convert.toLongArray(ancestors);
        placeMapper.updatePlaceStatusNormal(placeIds);
    }

    /**
     * 修改子元素关系
     *
     * @param placeId 被修改的空间位置ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updatePlaceChildren(Long placeId, String newAncestors, String oldAncestors)
    {
        List<SysPlace> children = placeMapper.selectChildrenPlaceById(placeId);
        for (SysPlace child : children)
        {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0)
        {
            placeMapper.updatePlaceChildren(children);
        }
    }

    /**
     * 删除空间位置管理信息
     *
     * @param placeId 空间位置ID
     * @return 结果
     */
    @Override
    public int deletePlaceById(Long placeId) {
        return placeMapper.deletePlaceById(placeId);
    }

    @Override
    public List<SysPlace> selectPlaceByPlaceName(String placeName) {
        return placeMapper.selectPlaceByPlaceName(placeName);
    }

    @Override
    public List<SysPlace> selectPlaceByIds(List<Long> ids) {
        return placeMapper.selectPlaceByIds(ids);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysPlace> list, SysPlace t) {
        // 得到子节点列表
        List<SysPlace> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysPlace tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysPlace> getChildList(List<SysPlace> list, SysPlace t)
    {
        List<SysPlace> tlist = new ArrayList<SysPlace>();
        Iterator<SysPlace> it = list.iterator();
        while (it.hasNext())
        {
            SysPlace n = (SysPlace) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getPlaceId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysPlace> list, SysPlace t)
    {
        return getChildList(list, t).size() > 0;
    }
}
